#include "Subview.h"
#include "Neptuner.h"
#include "StringOps.h"
#include "Ark.h"

#include<fstream>

using namespace std;

Subview::Subview()
{
	m_nSerialNumber=0;
}

Subview::~Subview()
{
}

void Subview::printElement(bool bClear)
{
	*m_pxOut<<"			<tr>";

	int i, n=m_asOutputRow.size();
	std::string sEnd=",", sStart ="";
	sStart ="<td>"; sEnd = "</td>"; 

	for(i=0; i<n; i++)
	{
		*m_pxOut<<sStart<< m_asOutputRow[i]<<sEnd;
	}
	*m_pxOut<<endl;

	*m_pxOut<<"			</tr>"<<endl;

	if(bClear) m_asOutputRow.clear();

}

void Subview::printFooting(bool bClear)
{
	*m_pxOut<<"			<tfoot>"<<endl;
	*m_pxOut<<"			<tr>";

	int i, n=m_asOutputRow.size();
	std::string sEnd=",", sStart ="";
	sStart ="<td>"; sEnd = "</td>"; 

	for(i=0; i<n; i++)
	{
		*m_pxOut<<sStart<< m_asOutputRow[i]<<sEnd;
	}
	*m_pxOut<<endl;

		*m_pxOut<<"			</tr>"<<endl;
		*m_pxOut<<"			</tfoot>"<<endl;

	if(bClear) m_asOutputRow.clear();
}

void Subview::printHeading(bool bClear)
{

	*m_pxOut<<"			<thead>" <<endl;
	*m_pxOut<<"			<tr>";

	int i, n=m_asOutputRow.size();
	std::string sEnd=",", sStart ="";
	sStart ="<th>"; sEnd = "</th>"; 

	for(i=0; i<n; i++)
	{
		*m_pxOut<<sStart<< m_asOutputRow[i]<<sEnd;
	}
	*m_pxOut<<endl;

	*m_pxOut<<"			</tr>"<<endl;
	*m_pxOut<<"			</thead>"<<endl;

	if(bClear) m_asOutputRow.clear();
}

void Subview::printBodyStart()
{
	*m_pxOut << "			<tbody>" << endl;
}

void Subview::printBodyEnd()
{
	*m_pxOut << "			</tbody>" << endl;
}

void Subview::generateHeader(){
std::string sNeptunerHome = Neptuner_getRelativizer(m_nLevel);
std::string sRelativizer = sNeptunerHome +"uboat/";
	*m_pxOut <<"<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>"<<endl;
	*m_pxOut <<"<html>"<<endl;
	*m_pxOut <<"<head>"<<endl;
	*m_pxOut <<"<title>" << m_sFilename<< " - Neptuner Submarine" "</title>";
	*m_pxOut <<"<link rel='shortcut icon' type='image/ico' href='"<<sRelativizer<<"neptunerIcon.jpg'>"<<endl;
	*m_pxOut <<"		<link rel='stylesheet' type='text/css' media='all' href='"<<sRelativizer<<"menu.css' />"<<endl;
	*m_pxOut <<"		<link rel='stylesheet' type='text/css' media='all' href='"<<sRelativizer<<"submarine.css' />"<<endl;
	*m_pxOut <<"		<script type='text/javascript' src='"<<sRelativizer<<"prototype.js'></script>"<<endl;
	*m_pxOut <<"		<script type='text/javascript' src='"<<sRelativizer<<"fastinit.js'></script>"<<endl;
	*m_pxOut <<"		<script type='text/javascript' src='"<<sRelativizer<<"tablesort.js'></script>"<<endl;
	*m_pxOut <<"		<script type='text/javascript' src='"<<sRelativizer<<"proto.menu.js'></script>"<<endl;
	*m_pxOut<< "<script type='text/javascript'>var nSourceLines = "<< m_nLines<<";";
	*m_pxOut<<"var sUBoatHome='"<<sRelativizer<<"';";
	*m_pxOut<<"var sNeptunerHome='"<<sNeptunerHome<<"';";
	*m_pxOut<<"var sFilename='"<<m_sFilename<<"';";
	*m_pxOut<<"</script>"<<endl;
	*m_pxOut <<"	</head>"<<endl;
}

void Subview::generateBody()
{
std::string sNeptunerHome = Neptuner_getRelativizer(m_nLevel);
std::string sRelativizer = sNeptunerHome +"uboat/";
*m_pxOut<<"<body>"<<endl;
*m_pxOut <<"		<script type='text/javascript' src='"<<sRelativizer<<"submarine.js'></script>"<<endl;

generatePaneSubmarine();
generatePaneReport();

}

void Subview::generateFooter()
{
*m_pxOut<< "</body>" << endl << "</html>" << endl;
}

void Subview::setOutputFile(std::string sOutFile)
{
	sOutFile = sOutFile + ".usub.html";
	Neptuner_createDirectoryFor(sOutFile);
	m_pxOut =  new std::ofstream(sOutFile.c_str());
	m_sOutputFile = sOutFile;
}

void Subview::outputReturns()
{
	m_nSerialNumber=0;

	*m_pxOut<<"<div id=tabReturns>"<<endl;
	*m_pxOut<<"			<table class=\"sortable\">" <<endl;

	m_asOutputRow.push_back("Index");
	m_asOutputRow.push_back("Function");
	m_asOutputRow.push_back("Return");
	m_asOutputRow.push_back("LineNumber");

	printHeading(false);
	printFooting();

    size_t nMethods;
	size_t nReturns;
    Method* pxMethod;

    nMethods = m_pxFuncalyzer->m_apxMethod.size();

	printBodyStart();
    for(size_t nLooper=0; nLooper<nMethods; nLooper++)
    {
        pxMethod = m_pxFuncalyzer->m_apxMethod[nLooper];
        if(!pxMethod)
			//tj: May be removed IMHO. Not doing for 0.10
            continue;

		nReturns = pxMethod->m_xReturn.m_asValues.size();
		
        for(size_t i=0;i<nReturns;i++)
        {
			m_nSerialNumber++;
			m_asOutputRow.push_back(stringify(m_nSerialNumber));

			m_asOutputRow.push_back(pxMethod->m_sName);
			m_asOutputRow.push_back(pxMethod->m_xReturn.m_asValues[i]); 
			m_asOutputRow.push_back(linkToUBoat(pxMethod->m_xReturn.m_anReturnPoint[i]));

			printElement();
        }
	}
	printBodyEnd();
	*m_pxOut<<"</table >";
	*m_pxOut<<"<br/>";
	*m_pxOut<<"</div/>";
}

void Subview::outputCalls()
{
	m_nSerialNumber=0;

	*m_pxOut<<"<div id=tabCalls>"<<endl;
	*m_pxOut<<"			<table class=\"sortable\">" <<endl;

	m_asOutputRow.push_back("Index");
	m_asOutputRow.push_back("Function");
	m_asOutputRow.push_back("Calls");
	m_asOutputRow.push_back("LineNumber");

	printHeading(false);
	printFooting();

	size_t nMethods = m_pxFuncalyzer->m_apxMethod.size();
    Method* pxMethod;

	printBodyStart();
	for(size_t nLooper=0;nLooper<nMethods;nLooper++)
    {
        pxMethod = m_pxFuncalyzer->m_apxMethod[nLooper];
        if(!pxMethod)
			//tj: May be removed IMHO. Not doing for 0.10
            continue;

        size_t nFuncCalls = pxMethod->m_asFunctionCall.size();
        for(size_t i=0; i< nFuncCalls; i++)
        {
			m_nSerialNumber++;
			m_asOutputRow.push_back(stringify(m_nSerialNumber));
            m_asOutputRow.push_back(pxMethod->m_sName);
            m_asOutputRow.push_back(pxMethod->m_asFunctionCall[i]);
            m_asOutputRow.push_back(linkToUBoat(pxMethod->m_anFunctionCallPoint[i]));

			printElement();
        }
	}
	printBodyEnd();
	*m_pxOut<<"</table >";
	*m_pxOut<<"<br/>";
	*m_pxOut<<"</div>";
}

void Subview::outputDataUsage()
{
	m_nSerialNumber=0;

	*m_pxOut<<"<div id=tabDataUsage>";
	*m_pxOut<<"			<table class=\"sortable\">" <<endl;

	m_asOutputRow.push_back("Index");
	m_asOutputRow.push_back("Function");
	m_asOutputRow.push_back("UsedData");
	m_asOutputRow.push_back("LineNumber");

	printHeading(false);
	printFooting();

    size_t nMethods = m_pxFuncalyzer->m_apxMethod.size();
    Method* pxMethod;

	printBodyStart();
    for(size_t nLooper=0;nLooper<nMethods;nLooper++)
    {
        pxMethod = m_pxFuncalyzer->m_apxMethod[nLooper];
        if(!pxMethod)
			//tj: May be removed IMHO. Not doing for 0.10
            continue;

		size_t nFuncCalls = pxMethod->m_asDataUse.size();
        for(size_t i=0; i< nFuncCalls; i++)
        {
			m_nSerialNumber++;
			m_asOutputRow.push_back(stringify(m_nSerialNumber));

			m_asOutputRow.push_back(pxMethod->m_sName);
            m_asOutputRow.push_back(pxMethod->m_asDataUse[i]);
            m_asOutputRow.push_back(linkToUBoat(pxMethod->m_anDataUsePoint[i]));

			printElement();
        }
	}
	printBodyEnd();
	*m_pxOut<<"</table >";
	*m_pxOut<<"<br/>";
	*m_pxOut<<"</div>";
}

void Subview::outputComplexity()
{
	m_nSerialNumber=0;
	*m_pxOut<<"<div id=tabComplexity>";
	*m_pxOut<<"			<table class=\"sortable\">" <<endl;

	m_asOutputRow.push_back("Index");
	m_asOutputRow.push_back("Name");
	m_asOutputRow.push_back("Nesting");
	m_asOutputRow.push_back("Exits");
	m_asOutputRow.push_back("Statements");
	m_asOutputRow.push_back("LoC");
	m_asOutputRow.push_back("Comments");
	m_asOutputRow.push_back("Paths");
	m_asOutputRow.push_back("Type");
	m_asOutputRow.push_back("Arguments");
	m_asOutputRow.push_back("Line");

	printHeading(false);
	printFooting();

    size_t nMethods = m_pxFuncalyzer->m_apxMethod.size();
    size_t nArguments;
    Method* pxMethod;

	printBodyStart();
    for(size_t nLooper=0;nLooper<nMethods;nLooper++)
    {
        pxMethod = m_pxFuncalyzer->m_apxMethod[nLooper];
        if(!pxMethod)
			//tj: May be removed IMHO. Not doing for 0.10
            continue;

		m_nSerialNumber++;

		nArguments = pxMethod->m_axArguments.size();

		m_asOutputRow.push_back(stringify(m_nSerialNumber));;
		m_asOutputRow.push_back(pxMethod->m_sName);
        m_asOutputRow.push_back(stringify(pxMethod->m_xComplexity.m_nMaxDepth));
		m_asOutputRow.push_back(stringify(pxMethod->m_xReturn.m_anReturnPoint.size()));
        m_asOutputRow.push_back(stringify(pxMethod->m_xComplexity.m_nStatements));
        m_asOutputRow.push_back(stringify(pxMethod->m_xComplexity.m_nLoC));
        m_asOutputRow.push_back(stringify(pxMethod->m_xComplexity.m_nLoCom));
        m_asOutputRow.push_back(stringify(pxMethod->m_xComplexity.m_nPaths));
        m_asOutputRow.push_back(pxMethod->m_xReturn.m_sType);
		m_asOutputRow.push_back(stringify(pxMethod->m_axArguments.size()));
		m_asOutputRow.push_back(linkToUBoat(pxMethod->m_nDefinePoint));

		printElement();
    }
	printBodyEnd();
	*m_pxOut<<"</table >";
	*m_pxOut<<"<br/>";
	*m_pxOut<<"</div >";
}

void Subview::linkify()
{
	Method* pxMethod;
	size_t nMethods = m_pxFuncalyzer->m_apxMethod.size();

    for(size_t nLooper=0;nLooper<nMethods;nLooper++)
    {
        pxMethod = m_pxFuncalyzer->m_apxMethod[nLooper];
        if(!pxMethod)
			//tj: May be removed IMHO. Not doing for 0.10
            continue;

		Symbol xSymbol;
		xSymbol.m_sName = pxMethod->m_sName;
		
		pxMethod->m_sName = Ark_getLinkForSymbol(xSymbol, m_pxFuncalyzer->m_pxCurrentScope, m_nLevel);
	}

}

std::string Subview::linkToUBoat(int nLine)
{
	static std::string sRelativizer = Neptuner_getRelativizer(m_nLevel)+"codebase/";
	static std::string sLink= "<a href="+ sRelativizer + m_sFilename + ".uboat.html#SL";

	std::string sOutput = sLink+ stringify(nLine) +">";
	sOutput+= (stringify(nLine)+"</a>");
	return sOutput;
}

void Subview::generatePaneSubmarine()
{
std::string sRelativizer = Neptuner_getRelativizer(m_nLevel)+ "uboat/";
*m_pxOut<<"<div id=paneSubmarine>"<<endl;
*m_pxOut<<"<div id=barTitle><img id='menuNeptuner' src='" << sRelativizer << "neptunerIcon.jpg'></img>"<<endl;
*m_pxOut<<"<strong>"<<getFilename(m_sFilename)<<"</strong></div>"<<endl;
*m_pxOut<<"<BR/>"<<endl;
*m_pxOut<<"<div id='reportChooser'>"<<endl;
*m_pxOut<<"<img src='" << sRelativizer << "report.png'> Reports</img>"<<endl;
*m_pxOut<<"<ul id=listReports>"<<endl;
*m_pxOut<<"<input type=radio name=typeReport onclick='showComplexity()'>Function Complexity</input><br/>"<<endl;
*m_pxOut<<"<input type=radio name=typeReport onclick='showCalls()'>Calls</input><br/>"<<endl;
*m_pxOut<<"<input type=radio name=typeReport onclick='showDataUsage()'>Data Usage</input><br/>"<<endl;
*m_pxOut<<"<input type=radio name=typeReport onclick='showReturns()'>Returns</input><br/>"<<endl;
*m_pxOut<<"</ul>"<<endl;
*m_pxOut<<"</div>"<<endl;

*m_pxOut<<"<div id=reportFilter>"<<endl;
generatePaneSidebar();
*m_pxOut<<"</div>"<<endl;
*m_pxOut<<"</div>"<<endl;

}

void Subview::generatePaneSidebar()
{
std::string sRelativizer = Neptuner_getRelativizer(m_nLevel)+"uboat/";
*m_pxOut<<"<div id=paneSidebar>"<<endl;
*m_pxOut<<"	<span id='sideBarTab'><img src='" << sRelativizer << "slidefilter.png' alt='sideBar' title='sideBar' onclick='toggleSidebar()'/></span>"<<endl;
*m_pxOut<<"	<div id='sideBarContents'>"<<endl;
*m_pxOut<<"		<div id='sideBarContentsInner'>"<<endl;

*m_pxOut<<"			<form id=formReportFilter>"<<endl;
*m_pxOut<<"			Filter: <input type='text' size=5 id=inpFilterString><br/>"<<endl;
*m_pxOut<<"			Field: <input type='text' size=5 id=inpFilterField><br/>"<<endl;
*m_pxOut<<"			<input type='button' value='Reset' onclick='alert('Feature not implemented. Wait for 0.21!')'>"<<endl;
*m_pxOut<<"			<input type='button' value='Search' onclick='alert('Feature not implemented. Wait for 0.21!')'><br/>"<<endl;
*m_pxOut<<"			<textarea cols='20' name='comments' rows='4' id='textareaFilterStatus'>Feature not implemented yet."<<endl;
*m_pxOut<<"Use table-sort functionality till then.</textarea>"<<endl;
*m_pxOut<<"			</form>"<<endl;

*m_pxOut<<"		</div>"<<endl;
*m_pxOut<<"	</div>"<<endl;
*m_pxOut<<"</div>"<<endl;
}

void Subview::generatePaneReport()
{
linkify();

*m_pxOut<<"<div id=paneReport>"<<endl;
outputComplexity();
outputCalls();
outputDataUsage();
outputReturns();
*m_pxOut<<"</div>"<<endl;
}

